home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / inline.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  8KB  |  311 lines

  1. /*
  2.  * @(#)inline.c    1.7  9/24/87
  3.  */
  4. #include "assert.h"
  5. #include "error.h"
  6. #include "ident.h"
  7. #include "nodes.h"
  8. #include "builtins.h"
  9. #include "sequence.h"
  10. #include "system.h"
  11. #include "trace.h"
  12. #include "opNames.h"
  13. #include "option.h"
  14.  
  15. /*
  16.  * inline's job is to decide if operations are inline-able, and set their
  17.  * isInLineAble bit in the b.opdef.  It also finds monitored operations 
  18.  * where signals happen as the last thing and sets the useSignalAndExit bit
  19.  * in b.signalstat.  It is also supposed to find objects that have monitors where 
  20.  * the monitor can be elided.
  21.  */
  22.  
  23. int countStatements(p)
  24. NodePtr p;
  25. {
  26.   register NodePtr q;
  27.   register int thisCount = 0;
  28.   
  29.   if ((int) p <= 0x200) return(0);
  30.   switch (p->tag) {
  31.     case P_ASSIGNSTAT:
  32.     case P_ASSERTSTAT:
  33.     case P_FIXSTAT:
  34.     case P_REFIXSTAT:
  35.     case P_UNFIXSTAT:
  36.     case P_MOVESTAT:
  37.     case P_PRIMSTAT:
  38.     case P_WAITSTAT:
  39.     case P_SIGNALSTAT:
  40.     case P_VARDECL:
  41.     case P_CONSTDECL:
  42.     case P_EXITSTAT:
  43.     case P_CHECKPOINTSTAT:
  44.     case P_RETURNSTAT:
  45.     case P_RETURNANDFAILSTAT:
  46.       return(1);
  47.     case P_IFSTAT:
  48.       thisCount = 1;
  49.       break;
  50.     default:
  51.       break;
  52.   }
  53.   Sequence_For(q, p)
  54.     thisCount += countStatements(q);
  55.   Sequence_Next
  56.   return(thisCount);
  57. }
  58.  
  59. int countNodes(p)
  60. NodePtr p;
  61. {
  62.   register NodePtr q;
  63.   register int thisCount = 1;
  64.   
  65.   if ((int) p <= 0x200) return(0);
  66.   Sequence_For(q, p)
  67.     thisCount += countNodes(q);
  68.   Sequence_Next
  69.   return(thisCount);
  70. }
  71.  
  72. #define INLINENODELIMIT 30
  73. #define INLINESTATEMENTLIMIT 3
  74.  
  75. typedef struct sFSRec {
  76.   NodePtr        signals;
  77.   Boolean        isStatement;
  78. } FSRec, *FSRecPtr;
  79.  
  80. FSRec findTerminalSignals(p)
  81. NodePtr p;
  82. {
  83.   register NodePtr q, r;
  84.   FSRec myResult, hisResult;
  85.   myResult.isStatement = FALSE;
  86.   myResult.signals = NULL;
  87.   
  88.   if ((int) p <= 0x200) return(myResult);
  89.   switch (p->tag) {
  90.     case P_FAILUREHANDLER:
  91.     case P_UNAVAILABLEHANDLER:
  92.       break;
  93.     case P_BLOCK:
  94.       return(findTerminalSignals(p->b.block.stats));
  95.     case T_SEQUENCE:
  96.       Sequence_For(q, p)
  97.     hisResult = findTerminalSignals(q);
  98.     /* merge the results */
  99.     if (hisResult.isStatement) {
  100.       Free(myResult.signals);
  101.       myResult.signals = NN;
  102.     }
  103.     Sequence_For(r, hisResult.signals)
  104.       Sequence_Add(&myResult.signals, r);
  105.     Sequence_Next
  106.     Free(hisResult.signals);
  107.       Sequence_Next
  108.       break;
  109.     case P_IFSTAT:
  110.       myResult.isStatement = TRUE;
  111.       Sequence_For(q, p->b.ifstat.ifclauses)
  112.     hisResult = findTerminalSignals(q->b.ifclause.stats);
  113.     Sequence_For(r, hisResult.signals)
  114.       Sequence_Add(&myResult.signals, r);
  115.     Sequence_Next
  116.     Free(hisResult.signals);
  117.       Sequence_Next
  118.       if ((q = p->b.ifstat.elseclause) != NN) {
  119.     hisResult = findTerminalSignals(q->b.elseclause.stats);
  120.     Sequence_For(r, hisResult.signals)
  121.       Sequence_Add(&myResult.signals, r);
  122.     Sequence_Next
  123.     Free(hisResult.signals);
  124.       }
  125.       break;
  126.     case P_IFCLAUSE:
  127.     case P_ELSECLAUSE:
  128.       break;
  129.     case P_LOOPSTAT:
  130.     case P_ASSIGNSTAT:
  131.     case P_ASSERTSTAT:
  132.     case P_REFIXSTAT:
  133.     case P_FIXSTAT:
  134.     case P_UNFIXSTAT:
  135.     case P_MOVESTAT:
  136.     case P_PRIMSTAT:
  137.     case P_WAITSTAT:
  138.     case P_VARDECL:
  139.     case P_CONSTDECL:
  140.     case P_EXITSTAT:
  141.     case P_CHECKPOINTSTAT:
  142.       myResult.isStatement = TRUE;
  143.       break;
  144.     case P_RETURNSTAT:
  145.     case P_RETURNANDFAILSTAT:
  146.       myResult.isStatement = FALSE;
  147.       break;
  148.     case P_SIGNALSTAT:
  149.       myResult.isStatement = TRUE;
  150.       Sequence_Add(&myResult.signals, p);
  151.       break;
  152.     default:
  153.       break;
  154.   }
  155.   return (myResult);
  156. }  
  157.  
  158. static int compareImports(left, right)
  159. NodePtr *left, *right;
  160. {
  161.   NodePtr l, r;
  162.   l = (*left)->b.setq.outer;
  163.   r = (*right)->b.setq.outer;
  164.   if (l->tag != P_SYMREF) return(-1);
  165.   if (r->tag != P_SYMREF) return(1);
  166.   return(l->b.symref.symbol->itsSymbolNumber -
  167.     r->b.symref.symbol->itsSymbolNumber);
  168. }
  169.  
  170. extern Boolean isARealImport();
  171.  
  172. static Boolean doImportsMatch(sig, obj)
  173. register NodePtr sig, obj;
  174. {
  175.   Symbol importedSym, aParam;
  176.   register NodePtr import;
  177.   register int nextParam = 0;
  178.   
  179.   TRACE2(imports, 1, "Checking object %s against signature %s", 
  180.     ATName(obj), SigName(sig));
  181.   Sequence_For(import, obj->b.oblit.setq)
  182.     if (isARealImport(import->b.setq.inner->b.symdef.symbol, FALSE)) {
  183.       if (import->b.setq.outer->tag != P_SYMREF) return(FALSE);
  184.       importedSym = import->b.setq.outer->b.symdef.symbol;
  185.       if (nextParam >= Sequence_Length(sig->b.opsig.params)) return(FALSE);
  186.       aParam = sig->b.opsig.params->b.children[nextParam]->b.param.sym->b.symdef.symbol;
  187.       TRACE2(imports, 1, "Symbol %s must match %s", STName(importedSym),
  188.     STName(aParam));
  189.       if (aParam == importedSym) {
  190.     nextParam ++;
  191.     TRACE0(imports, 1, "yes!");
  192.       } else {
  193.     TRACE0(imports, 1, "no!\nReturning FALSE");
  194.     return(FALSE);
  195.       }
  196.     }
  197.   Sequence_Next
  198.   TRACE0(imports, 1, "Returning TRUE");
  199.   return(TRUE);
  200. }
  201.  
  202. extern void DisplayTree();
  203.  
  204. checkWonderfullyImmutable(p)
  205. NodePtr p;
  206. {
  207.   if (p->b.oblit.process != NN) {
  208.     ErrorMessage(p, "Immutable objects may not contain processes");
  209.   }
  210.   if (p->b.oblit.monitor != NN &&
  211.       !p->b.oblit.monitor->b.monitor.mayBeElided &&
  212.       Sequence_Length(p->b.oblit.monitor->b.monitor.decls) != 0 &&
  213.       Sequence_Length(p->b.oblit.monitor->b.monitor.ops) != 0) {
  214.     ErrorMessage(p, "Immutable objects may not contain monitors");
  215.   }
  216. }
  217.  
  218. void detectInlines(p)
  219. NodePtr p;
  220. {
  221.   register NodePtr q;
  222.   FSRec andExitableSignals;
  223.   register Boolean isInlineable = TRUE;
  224.   Boolean done = FALSE;
  225.   
  226.   if ((int) p <= 0x200) return;
  227.   switch (p->tag) {
  228.     case P_CONSTDECL:
  229.       if (p->b.constdecl.sym->b.symdef.symbol->isManifest) {
  230.     detectInlines(p->b.constdecl.sym->b.symdef.symbol->value.value);
  231.     done = TRUE;
  232.       }
  233.       break;
  234.     case P_INVOC:
  235.     default:
  236.       break;
  237.   }
  238.   if (!done) Sequence_For(q, p)
  239.     if ((int)q > 0x200) detectInlines(q);
  240.   Sequence_Next
  241.   switch (p->tag) {
  242.     case P_OBLIT:
  243.       if (! p->b.oblit.f.isTypeVariable &&
  244.           ! p->b.oblit.f.dependsOnTypeVariable &&
  245.       ! p->b.oblit.f.isManifest) {
  246.     if (Sequence_Length(p->b.oblit.setq) > 1) {
  247.       IFTRACE(imports, 1) {
  248.         trace(1, "Sorting imports of %s", ATName(p));
  249.         trace(1, "Before:");
  250.         DisplayTree(stdout, p->b.oblit.setq, 0, 999);
  251.       }
  252.       qsort((char *)&(p->b.oblit.setq->b.children[0]),
  253.         Sequence_Length(p->b.oblit.setq),
  254.         sizeof(NodePtr),
  255.         compareImports);
  256.       IFTRACE(imports, 1) {
  257.         trace(1, "After:");
  258.         DisplayTree(stdout, p->b.oblit.setq, 0, 999);
  259.       }
  260.     }
  261.       }
  262.       if (p->b.oblit.f.immutable) {
  263.     checkWonderfullyImmutable(p);
  264.       }
  265.       break;
  266.     
  267.     case P_OPDEF:
  268. #define PESSIMISTIC
  269. #ifdef PESSIMISTIC
  270.       q = p->b.opdef.body;
  271.       if (q->b.block.failurehandler != NN) isInlineable = FALSE;
  272.       else if (q->b.block.unavailablehandler != NN) isInlineable = FALSE;
  273.       else {
  274.     q = q->b.block.stats;
  275.     if (Sequence_Length(q) != 1) isInlineable = FALSE;
  276.     else if (q->b.children[0]->tag == P_PRIMSTAT) isInlineable = TRUE;
  277.     else if (q->b.children[0]->tag == P_ASSIGNSTAT) {
  278.       q = q->b.children[0];
  279.       if (Sequence_Length(p->b.opdef.sig->b.opsig.results) != 1) isInlineable = FALSE;
  280.       else if (q->b.assignstat.right->nChildren != 1) isInlineable = FALSE;
  281.       else if (q->b.assignstat.left->nChildren != 1) isInlineable = FALSE;
  282.       else if (q->b.assignstat.right->b.children[0]->tag == P_OBLIT) {
  283.         isInlineable = doImportsMatch(p->b.opdef.sig,
  284.           q->b.assignstat.right->b.children[0]);
  285.       } else IFOPTION(inline, 1) {
  286.         isInlineable = TRUE;
  287.       } else {
  288.         isInlineable = FALSE;
  289.       }
  290.     } else {
  291.       isInlineable = FALSE;
  292.     }
  293.       }
  294.       p->b.opdef.isInlineable = isInlineable;
  295. #else
  296.       if (countNodes(p) <= INLINENODELIMIT && countStatements(p) <= INLINESTATEMENTLIMIT) {
  297.     p->b.opdef.isInlineable = TRUE;
  298.       }
  299. #endif
  300.       andExitableSignals = findTerminalSignals(p->b.opdef.body);
  301.       Sequence_For(q, andExitableSignals.signals)
  302.     assert(q->tag == P_SIGNALSTAT);
  303.     q->b.signalstat.useSignalAndExit = TRUE;
  304.       Sequence_Next
  305.       Free(andExitableSignals.signals);
  306.       break;
  307.     default:
  308.       break;
  309.   }
  310. }
  311.